import memcache
import datetime
import random
import string
import time
from PIL import Image
from io import BytesIO
from urllib.parse import quote

from wechatpy import WeChatClient
from wechatpy.oauth import WeChatOAuth
from wechatpy.client.api.jsapi import WeChatJSAPI
from wechatpy.pay import WeChatPay
from core.tools.FormatXmlArray import FormatXmlArray

# from finance_c2c.local_settings import KaLaiBaoConfig
# from finance_c2c.local_settings import Config

# mc = memcache.Client(['10.24.200.174:11211'], debug=0)

# mc = memcache.Client(['m-2zece214aca716c4.memcache.rds.aliyuncs.com:11211'], debug=0)
# mc = memcache.Client(['m-2zece214aca716c4705.memcache.rds.aliyuncs.com:11211'], debug=0)
# mc = memcache.Client(['m-2zeg2m24xe41b5zqg452.mysql.rds.aliyuncs.com:11211'], debug=0)
# VPC
mc = memcache.Client(['m-2zece214aca716c4705.memcache.rds.aliyuncs.com:11211'], debug=0)


class WxBase(object):
    def __init__(self, config="default"):
        if config == "default":
            from finance_c2c.local_settings import Config
        else:
            from finance_c2c.local_settings import KaLaiBaoConfig as Config
        self.config = Config
        self.appid = Config.appid
        self.token = Config.token
        self.appsecret = Config.appsecret
        self.encrypt_mode = Config.encrypt_mode
        self.api_key = Config.api_key
        self.mch_id = Config.mch_id
        self.mch_cert = Config.mch_cert
        self.mch_key = Config.mch_key
        self.access_token = None

    @property
    def client(self):
        return self.get_client(self.config)

    def get_client(self, config):
        access_token = self.get_access_token_from_mc(config)
        self.access_token = access_token
        return WeChatClient(self.appid, self.appsecret, access_token=access_token)

    def get_access_token_from_mc(self, config):
        """
        从缓存中获取 access_token
        :return:
        """
        if not mc.get("token_1%s" % config.appid):
            result_dict = WeChatClient(self.appid, self.appsecret).fetch_access_token()
            mc.set("token_1%s" % config.appid, result_dict.get('access_token'), 7000)
            return result_dict.get('access_token')
        else:
            return mc.get("token_1%s" % config.appid)

    def get_we_chat_OAuth(self, redirect_uri, scope='snsapi_base'):
        return WeChatOAuth(self.appid, self.appsecret, redirect_uri, scope=scope)

    def __scene_str(self, content, short=True):
        """
        :param short: True 则显示短期，时间自己定义   False则是长期二维码
        :param content: 自定义内容
        :return:
        """
        if short:
            data = {
                "expire_seconds": 2592000,
                "action_name": "QR_STR_SCENE",
                "action_info": {"scene": {"scene_str": content}, }
            }
        else:
            data = {
                "action_name": "QR_LIMIT_STR_SCENE",
                "action_info": {"scene": {"scene_str": content}, }
            }
        res = self.client.qrcode.create(data)
        return res

    def get_qr_url(self, content, short=True):
        """
        获取二维码地址
        :param content:
        :param short:
        :return:
        """
        res = self.__scene_str(content, short=short)
        return self.client.qrcode.get_url(res.get("ticket"))

    def get_qr_file(self, content, short=True):
        """
        获取二维码文件
        :param content:
        :param short:
        :return:
        """
        res = self.__scene_str(content, short=short)
        file_response = self.client.qrcode.show(res.get("ticket"))
        return Image.open(BytesIO(file_response.content))

    def get_qr_response(self, content, short=True):
        """
        获取二维码文件
        :param content:
        :param short:
        :return:
        """
        res = self.__scene_str(content, short=short)
        file_response = self.client.qrcode.show(res.get("ticket"))
        return file_response.content

    def __get_js_ticket_from_mc(self, js_api):
        if not mc.get("c2c_js_ticket_%s" % self.appid):
            ticket = js_api.get_jsapi_ticket()
            return ticket
        else:
            return mc.get("c2c_js_ticket_%s" % self.appid)

    def get_sign(self, url):
        """
        获取分享需要的签名
        :param url:
        :return:
        """
        js_api = WeChatJSAPI(self.client)
        ticket = self.__get_js_ticket_from_mc(js_api)
        noncestr = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(15))
        timestamp = int(time.time())
        signature = js_api.get_jsapi_signature(noncestr, ticket, timestamp, url)
        return {
            'nonceStr': noncestr,
            'signatures': signature,
            'timestamps': timestamp,
            'appid': self.appid
        }

    def upload_file(self, file_type, media_file):
        """
        临时文件
        :param file_type: 分别有图片（image）、语音（voice）、视频（video）和缩略图（thumb）
        :param media_file: 文件地址
        :return:
        """
        media_file = open(media_file, 'rb')
        res = self.client.media.upload(file_type, media_file)
        return res

    def send_image(self, openid, media_id):
        """
        客服接口，主动发送消息 发送图片消息
        :return:
        """
        res = self.client.message.send_image(openid, media_id)

    def send_text(self, openid, content):
        res = self.client.message.send_text(openid, content)

    def wx_pay(self):
        return WeChatPay(self.appid, self.api_key, self.mch_id, mch_cert=self.mch_cert, mch_key=self.mch_key,
                         sandbox=False)


class WxPay(WeChatPay):
    def __init__(self, config="default"):
        if config == "default":
            from finance_c2c.local_settings import Config
        else:
            from finance_c2c.local_settings import KaLaiBaoConfig as Config
        super(WxPay, self).__init__(Config.appid, Config.api_key, Config.mch_id, mch_cert=Config.mch_cert,
                                    mch_key=Config.mch_key)

    @property
    def out_trade_no(self):
        now = datetime.datetime.now()
        out_trade_no = '{0}{1}{2}'.format(
            self.mch_id,
            now.strftime('%Y%m%d%H%M%S'),
            random.randint(1000, 10000)
        )
        return out_trade_no

    @property
    def nonce_str(self, length=32):
        """
        随机字符串，不长于32位
        :param length:
        :return:
        """
        chars = "abcdefghijklmnopqrstuvwxyz0123456789"
        strs = []
        for x in range(length):
            strs.append(chars[random.randrange(0, len(chars))])
        return "".join(strs)

    def query_transfer_order(self, out_trade_no):
        """
        查看企业付款状态
        :param out_trade_no:
        :return: SUCCESS:转账成功, FAILED:转账失败, 要不然就是接口错误
        """
        info = self.transfer.query(out_trade_no=out_trade_no)
        info = FormatXmlArray.xml_to_array(info)
        if info.get("err_code") == "SYSTEMERROR":
            return self.query_transfer_order(out_trade_no)
        else:
            if info.get("status") == "PROCESSING":
                return self.query_transfer_order(out_trade_no)
            else:
                return info

    # 提现到银行卡手续费
    @staticmethod
    def get_amount(amount):
        server_charge = amount * 0.001
        if server_charge > 100:
            return amount - server_charge
        else:
            return amount - 100
